<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>01认识 RxJS · ShaofeiZi Blog · 做个日常记录</title>
    <meta name="description" content="訾绍飞的博客。万物皆有裂缝处，那是光射进来的地方。">
    <link rel="shortcut icon" href="/BLOG/favicon.ico">
  <link rel="manifest" href="/BLOG/manifest.json">
  <meta name="theme-color" content="#3F51B5">
  <meta name="apple-mobile-web-app-capable" content="yes">
  <meta name="apple-mobile-web-app-status-bar-style" content="black">
  <link rel="apple-touch-icon" href="/BLOG/icons/192.png">
  <link rel="mask-icon" href="/BLOG/icons/safari-pinned-tab.svg" color="#3eaf7c">
  <meta name="msapplication-TileImage" content="/icons/192.png">
  <meta name="msapplication-TileColor" content="#3F51B5">
    
    <link rel="preload" href="/BLOG/assets/css/42.styles.90045bd1.css" as="style"><link rel="preload" href="/BLOG/assets/js/app.1a725be8.js" as="script"><link rel="preload" href="/BLOG/assets/js/33.ad2b89cc.js" as="script"><link rel="prefetch" href="/BLOG/assets/js/7.88ba0bb7.js"><link rel="prefetch" href="/BLOG/assets/js/0.d3e592bd.js"><link rel="prefetch" href="/BLOG/assets/js/1.39b9c99c.js"><link rel="prefetch" href="/BLOG/assets/js/2.68dc10c9.js"><link rel="prefetch" href="/BLOG/assets/js/3.dfebdd5e.js"><link rel="prefetch" href="/BLOG/assets/js/4.ea97a821.js"><link rel="prefetch" href="/BLOG/assets/js/5.d8c2ecbf.js"><link rel="prefetch" href="/BLOG/assets/js/6.e51cd79c.js"><link rel="prefetch" href="/BLOG/assets/js/8.d9eebc06.js"><link rel="prefetch" href="/BLOG/assets/js/9.1a541d13.js"><link rel="prefetch" href="/BLOG/assets/js/10.4ec9ca67.js"><link rel="prefetch" href="/BLOG/assets/js/11.02558377.js"><link rel="prefetch" href="/BLOG/assets/js/12.d0e2086f.js"><link rel="prefetch" href="/BLOG/assets/js/13.5af02ddd.js"><link rel="prefetch" href="/BLOG/assets/js/14.5d9fcbf2.js"><link rel="prefetch" href="/BLOG/assets/js/15.ca0178b2.js"><link rel="prefetch" href="/BLOG/assets/js/16.cd99d056.js"><link rel="prefetch" href="/BLOG/assets/js/17.56f11c1d.js"><link rel="prefetch" href="/BLOG/assets/js/18.21837cc7.js"><link rel="prefetch" href="/BLOG/assets/js/19.73335fea.js"><link rel="prefetch" href="/BLOG/assets/js/20.1632ab79.js"><link rel="prefetch" href="/BLOG/assets/js/21.43175244.js"><link rel="prefetch" href="/BLOG/assets/js/22.5b7c0cca.js"><link rel="prefetch" href="/BLOG/assets/js/23.e624ba97.js"><link rel="prefetch" href="/BLOG/assets/js/24.ac5f7b41.js"><link rel="prefetch" href="/BLOG/assets/js/25.6934a11d.js"><link rel="prefetch" href="/BLOG/assets/js/26.407b2583.js"><link rel="prefetch" href="/BLOG/assets/js/27.7449d673.js"><link rel="prefetch" href="/BLOG/assets/js/28.52e25437.js"><link rel="prefetch" href="/BLOG/assets/js/29.fba21f3a.js"><link rel="prefetch" href="/BLOG/assets/js/30.2cd6d3e2.js"><link rel="prefetch" href="/BLOG/assets/js/31.0b0a749f.js"><link rel="prefetch" href="/BLOG/assets/js/32.92134487.js"><link rel="prefetch" href="/BLOG/assets/js/34.9b22334e.js"><link rel="prefetch" href="/BLOG/assets/js/35.825f3d75.js"><link rel="prefetch" href="/BLOG/assets/js/36.cc3da84c.js"><link rel="prefetch" href="/BLOG/assets/js/37.8f339f62.js"><link rel="prefetch" href="/BLOG/assets/js/38.5674618f.js"><link rel="prefetch" href="/BLOG/assets/js/39.180f0d85.js"><link rel="prefetch" href="/BLOG/assets/js/40.275f26e3.js"><link rel="prefetch" href="/BLOG/assets/js/41.ce0f5927.js">
    <link rel="stylesheet" href="/BLOG/assets/css/42.styles.90045bd1.css">
  </head>
  <body>
    <div id="app" data-server-rendered="true"><div data-app="true" id="app" class="application theme--light"><div class="application--wrap"><div class="v-progress-linear blog-progress" style="height:3px;display:none;"><div class="v-progress-linear__background accent" style="height:3px;opacity:0.4;width:100%;"></div><div class="v-progress-linear__bar"><!----><div class="v-progress-linear__bar__determinate accent" style="width:0%;"></div></div></div><aside class="v-navigation-drawer v-navigation-drawer--close v-navigation-drawer--fixed v-navigation-drawer--is-mobile" style="height:100%;margin-top:0px;max-height:calc(100% - 0px);transform:translateX(-240px);width:240px;"><div><div class="aside-brand-wrap"><div class="aside-brand"><a href="/BLOG/" class="aside-avatar elevation-2 router-link-active"><img src="/BLOG/face.png" alt="avatar"></a><hgroup class="mt-3 variant-hide"><div class="subheading white--text">訾绍飞</div><a href="mailto:zishaofei221@gmail.com" title="zishaofei221@gmail.com" class="aside-mail primary--text text--lighten-5">zishaofei221@gmail.com</a></hgroup></div></div><hr class="v-divider theme--dark"><div class="v-list nav-list"><div class="secondary--text"><a href="/BLOG/" class="v-list__tile v-list__tile--link"><div class="v-list__tile__avatar"><div class="v-avatar" style="height:40px;width:40px;"><i class="fa fa-home"></i></div></div><div class="v-list__tile__content">首页</div></a></div><div class="secondary--text"><a href="/BLOG/tags" class="v-list__tile v-list__tile--link"><div class="v-list__tile__avatar"><div class="v-avatar" style="height:40px;width:40px;"><i class="fa fa-tag"></i></div></div><div class="v-list__tile__content">标签</div></a></div><div class="secondary--text"><a href="https://github.com/ShaofeiZi" target="_blank" class="v-list__tile v-list__tile--link"><div class="v-list__tile__avatar"><div class="v-avatar" style="height:40px;width:40px;"><i class="fab fa-github"></i></div></div><div class="v-list__tile__content">Github</div></a></div><div class="secondary--text"><a href="/BLOG/about" class="v-list__tile v-list__tile--link"><div class="v-list__tile__avatar"><div class="v-avatar" style="height:40px;width:40px;"><i class="fa fa-user-secret"></i></div></div><div class="v-list__tile__content">About</div></a></div></div></div><div class="v-navigation-drawer__border"></div></aside><nav class="blog-toolbar v-toolbar v-toolbar--fixed theme--dark primary" style="margin-top:0px;padding-right:0px;padding-left:0px;transform:translateY(0px);"><div class="v-toolbar__content" style="height:56px;"><button type="button" class="v-btn v-btn--icon"><div class="v-btn__content"><i class="fa fa-bars"></i></div></button><div class="v-toolbar__title">01认识 RxJS</div><div class="spacer"></div><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""><!----></div><div class="v-menu" style="display:none;"><div class="v-menu__activator"><button type="button" class="v-btn v-btn--icon"><div class="v-btn__content"><i class="fa fa-share-alt"></i></div></button></div><div class="v-menu__content" style="max-height:auto;min-width:0px;max-width:auto;top:12px;left:0px;transform-origin:top right;z-index:0;display:none;"><div class="v-list"><div class="secondary--text"><a class="v-list__tile v-list__tile--link"><div class="v-list__tile__avatar"><div class="v-avatar" style="height:40px;width:40px;"><i class="fa fa-lg fa-copy"></i></div></div><div class="v-list__tile__title">复制链接</div></a></div></div><input type="text" tabindex="-1" aria-hidden="true" value="" class="fake-hide"></div></div></div></nav><main class="v-content" style="padding-top:56px;padding-right:0px;padding-bottom:0px;padding-left:0px;"><div class="v-content__wrap"><div class="container blog-container grid-list-xl align-center"><div class="layout row wrap"><div class="flex mb-3 xs12"><article class="v-card elevation-16 post-card" style="height:undefined;"><div class="v-card__title"><div class="flex xs12"><h2 class="display-1 mb-3">01认识 RxJS</h2><div class="post-meta"><time datetime="2018-04-29T12:15:53.000Z" class="secondary--text post-time">2018年04月29日</time></div></div></div><div class="v-card__text pt-0 pb-0"><div class="flex xs12"><div class="content custom"><h1 id="_30-天精通-rxjs-01-：认识-rxjs"><a href="#_30-天精通-rxjs-01-：认识-rxjs" aria-hidden="true" class="header-anchor">#</a> 30 天精通 RxJS (01)：认识 RxJS</h1><blockquote><p>RxJS 是笔者认为未来几年内会非常红的 Library，RxJS 提供了一套完整的非同步解决方案，让我们在面对各种非同步行为，不管是 Event, AJAX, 还是 Animation 等，我们都可以使用相同的 API (Application Programming Interface) 做开发。</p></blockquote><p><img src="https://raw.githubusercontent.com/Reactive-Extensions/RxJS/master/logos/logo.png" alt="RxJS Logo"></p><p>这是【30天精通 RxJS】的 01 篇，如果还没看过 00 篇可以往这边走：
<a href="https://github.com/ShaofeiZi/30-days-proficient-in-rxjs/blob/master/30%E5%A4%A9%E7%B2%BE%E9%80%9ARXJS%EF%BC%8801%EF%BC%89%EF%BC%9A%E5%85%B3%E4%BA%8E.md" target="_blank" rel="noopener noreferrer">30 天精通 RxJS (00)： 关于本系列文章</a></p><p>在网页的世界存取任何资源都是非同步(Async)的，比如说我们希望拿到一个档案，要先发送一个请求，然后必须等到档案回来，再执行对这个档案的操作。这就是一个非同步的行为，而随着网页需求的复杂化，我们所写的 JavaScript 就有各种针对非同步行为的写法，例如使用 callback 或是 Promise 对象甚至是新的语法糖 async/await —— 但随着应用需求愈来愈复杂，撰写非同步的代码仍然非常困难。</p><h2 id="非同步常见的问题"><a href="#非同步常见的问题" aria-hidden="true" class="header-anchor">#</a> 非同步常见的问题</h2><ul><li>竞态条件 (Race Condition)</li><li>内存泄漏 (Memory Leak)</li><li>复杂的状态 (Complex State)</li><li>例外处理 (Exception Handling)</li></ul><h3 id="race-condition"><a href="#race-condition" aria-hidden="true" class="header-anchor">#</a><a href="https://goo.gl/GlNLYl" target="_blank" rel="noopener noreferrer">Race Condition</a></h3><p>每当我们对同一个资源同时做多次的非同步存取时，就可能发生 Race Condition 的问题。比如说我们发了一个 Request 更新使用者资料，然后我们又立即发送另一个 Request 取得使用者资料，这时第一个 Request 和第二个 Request 先后顺序就会影响到最终接收到的结果不同，这就是 Race Condition。</p><h3 id="memory-leak"><a href="#memory-leak" aria-hidden="true" class="header-anchor">#</a><a href="https://en.wikipedia.org/wiki/Memory_leak" target="_blank" rel="noopener noreferrer">Memory Leak</a></h3><p>Memory Leak 是最常被大家忽略的一点。原因是在传统网站的行为，我们每次换页都是整页重刷，并重新执行 JavaScript，所以不太需要理会内存的问题！但是当我们希望将网站做得像应用程式时，这件事就变得很重要。例如做 <a href="https://en.wikipedia.org/wiki/Single-page_application" target="_blank" rel="noopener noreferrer">SPA</a> (Single Page Application) 网站时，我们是透过 JavaScript 来达到切换页面的内容，这时如果有对 DOM 注册监听事件，而没有在适当的时机点把监听的事件移除，就有可能造成 Memory Leak。比如说在 A 页面监听 body 的 scroll 事件，但页面切换时，没有把 scroll 的监听事件移除。</p><h3 id="complex-state"><a href="#complex-state" aria-hidden="true" class="header-anchor">#</a> Complex State</h3><p>当有非同步行为时，应用程式的状态就会变得非常复杂！比如说我们有一支付费用户才能播放的视频，首先可能要先抓取这部视频的资讯，接着我们要在播放时去验证使用者是否有权限播放，而使用者也有可能再按下播放后又立即按了取消，而这些都是非同步执行，这时就会各种复杂的状态需要处理。</p><h3 id="exception-handling"><a href="#exception-handling" aria-hidden="true" class="header-anchor">#</a> Exception Handling</h3><p>JavaScript 的 try/catch 可以捕捉同步的例外，但非同步的程式就没这么容易，尤其当我们的非同步行为很复杂时，这个问题就愈加明显。</p><h2 id="各种不同的-api"><a href="#各种不同的-api" aria-hidden="true" class="header-anchor">#</a> 各种不同的 API</h2><p>我们除了要面对非同步会遇到的各种问题外，还需要烦恼很多不同的 API</p><ul><li>DOM Events</li><li>XMLHttpRequest</li><li>fetch</li><li>WebSockets</li><li>Server Send Events</li><li>Service Worker</li><li>Node Stream</li><li>Timer</li></ul><p>上面列的 API 都是非同步的，但他们都有各自的 API 及写法！如果我们使用 RxJS，上面所有的 API 都可以透过 RxJS 来处理，就能用同样的 API 操作 (RxJS 的 API)。</p><p>这里我们举一个例子，假如我们想要监听点击事件(click event)，但点击一次之后不再监听。</p><p><strong>原生 JavaScript</strong></p><pre class="language-javascript"><code><span class="token keyword">var</span> <span class="token function-variable function">handler</span> <span class="token operator">=</span> <span class="token punctuation">(</span>e<span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
	console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>e<span class="token punctuation">)</span><span class="token punctuation">;</span>
	document<span class="token punctuation">.</span>body<span class="token punctuation">.</span><span class="token function">removeEventListener</span><span class="token punctuation">(</span><span class="token string">'click'</span><span class="token punctuation">,</span> handler<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 结束监听</span>
<span class="token punctuation">}</span>

<span class="token comment">// 注册监听</span>
document<span class="token punctuation">.</span>body<span class="token punctuation">.</span><span class="token function">addEventListener</span><span class="token punctuation">(</span><span class="token string">'click'</span><span class="token punctuation">,</span> handler<span class="token punctuation">)</span><span class="token punctuation">;</span>

</code></pre><p><strong>使用 Rx 大概的样子</strong></p><pre class="language-javascript"><code>Rx<span class="token punctuation">.</span>Observable
	<span class="token punctuation">.</span><span class="token function">fromEvent</span><span class="token punctuation">(</span>document<span class="token punctuation">.</span>body<span class="token punctuation">,</span> <span class="token string">'click'</span><span class="token punctuation">)</span> <span class="token comment">// 注册监听</span>
	<span class="token punctuation">.</span><span class="token function">take</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span> <span class="token comment">// 只取一次</span>
	<span class="token punctuation">.</span><span class="token function">subscribe</span><span class="token punctuation">(</span>console<span class="token punctuation">.</span>log<span class="token punctuation">)</span><span class="token punctuation">;</span>

</code></pre><p><a href="https://jsbin.com/vofaluv/4/edit?console,output" target="_blank" rel="noopener noreferrer">JSbin</a> | <a href="https://jsfiddle.net/s6323859/d95a8peo/1/" target="_blank" rel="noopener noreferrer">JSFiddle</a>
(点击画面后会在 console 显示，记得打开 console 来看)</p><p>大致上能看得出来我们在使用 RxJS 后，不管是针对 DOM Event 还是上面列的各种 API 我们都可以透过 RxJS 的 API 来做资料操作，像是示例中用 <code>take(n)</code> 来设定只取一次，之后就释放内存。</p><p>说了这么多，其实就是简单一句话</p><p><strong>在面对日益复杂的问题，我们需要一个更好的解决方法。</strong></p><h2 id="rxjs-基本介绍"><a href="#rxjs-基本介绍" aria-hidden="true" class="header-anchor">#</a> RxJS 基本介绍</h2><p>RxJS 是一套借由 <strong>Observable sequences</strong> 来组合<strong>非同步行为</strong>和<strong>事件基础</strong>程序的 Library！</p><blockquote><p>可以把 RxJS 想成处理 非同步行为 的 Lodash。</p></blockquote><p>这也被称为 Functional Reactive Programming，更切确地说是指 Functional Programming 及 Reactive Programming 两个编程思想的结合。</p><blockquote><p>RxJS 确实是 Functional Programming 跟 Reactive Programming 的结合，但能不能称为 Functional Reactive Programming (FRP) 一直有争议。</p></blockquote><blockquote><p>Rx 在<a href="http://reactivex.io/intro.html" target="_blank" rel="noopener noreferrer">官网</a>上特别指出，有时这会被称为 FRP 但这其实是个“误称”。</p></blockquote><blockquote><p>简单说 FRP 是操作随着时间<strong>连续性改变的数值</strong> 而 Rx 则比较像是操作随着时间发出的<strong>离散数值</strong>，这个部份读者不用分得太细，因为 FRP 的定义及解释一直存在着歧异，也有众多大神为此争论，如下</p></blockquote><blockquote><p><a href="https://medium.com/@andrestaltz/why-i-cannot-say-frp-but-i-just-did-d5ffaa23973b#.dhmsyic9w" target="_blank" rel="noopener noreferrer">André Staltz</a>：Rx 著名的推广者，也是 RxJS 5 主要贡献者之一，同时是 Cycle.js 的作者。Staltz 特别写了一篇<a href="https://medium.com/@andrestaltz/why-i-cannot-say-frp-but-i-just-did-d5ffaa23973b#.dhmsyic9w" target="_blank" rel="noopener noreferrer">文章</a>解释为什么 Rx 不能说是 FRP 但他仍然称其为 FRP。</p></blockquote><blockquote><p><a href="https://twitter.com/_juandg" target="_blank" rel="noopener noreferrer">Juan Gomez</a>：曾在 Netflix 工作，目前任职于 Fitbit，经常出现在国外演讨会，主要写 Android。Juan Gomez 在 <a href="https://realm.io/news/droidcon-gomez-functional-reactive-programming/" target="_blank" rel="noopener noreferrer">Droidcon NYC 2015 的演讲</a>中特别提出他坚持称 Rx 为 FRP。</p></blockquote><blockquote><p><a href="https://twitter.com/czaplic" target="_blank" rel="noopener noreferrer">Evan Czaplicki</a>：任职于 NoRedInk，Elm 的作者。Evan 在 <a href="https://www.youtube.com/watch?v=Agu6jipKfYw" target="_blank" rel="noopener noreferrer">StrangeLoop 2014 的演讲</a>中，特别为现在各种 FRP 的不同解释做分类。</p></blockquote><blockquote><p>笔者自己的看法是比较偏向直接称 Rx 为 FRP，原因是这较为直觉(FP + RP = FRP)，也比较不会对新手造成困惑，另外就是其他各种编程范式(包含 OOP, FP)其实都是<strong>想法的集合，而非严格的指南(Guideline)</strong>，我们应该更宽松的看待 FRP 而不是给他一个严格的定义。</p></blockquote><h3 id="关于-reactive-extension-rx"><a href="#关于-reactive-extension-rx" aria-hidden="true" class="header-anchor">#</a> 关于 Reactive Extension (Rx)</h3><p>Rx 最早是由微软开发的 LinQ 扩展出来的开源专案，之后主要由社群的工程师贡献，有多种语言支援，也被许多科技公司所采用，如 Netflix, Trello, Github, Airbnb...等。</p><h4 id="rx-的相关资讯"><a href="#rx-的相关资讯" aria-hidden="true" class="header-anchor">#</a> Rx 的相关资讯</h4><ul><li>开源专案 (Apache 2.0 License)</li><li>多种语言支持
<ul><li>JavaScript</li><li>Java</li><li>C#</li><li>Python</li><li>Ruby</li><li>...(太多了列不完)</li></ul></li><li><a href="http://reactivex.io/" target="_blank" rel="noopener noreferrer">官网</a></li><li><s>微软目前最成功的开源专案</s></li></ul><blockquote><p>LinQ 唸做 Link，全名是 Language-Integrated Query，其功能很多元也非常强大；学 RxJS 可以不用会。</p></blockquote><h3 id="functional-reactive-programming"><a href="#functional-reactive-programming" aria-hidden="true" class="header-anchor">#</a> Functional Reactive Programming</h3><p>Functional Reactive Programming 是一种编程范式(programming paradigm)，白话就是一种<strong>写程式的方法论</strong>！举个例子，像 OOP 就是一种编程范式，OOP 告诉我们要使用对象的方式来思考问题，以及撰写程式。而 Functional Reactive Programming 其实涵盖了 Reactive Programming 及 Functional Programming 两种编程思想。</p><p><strong>Functional Programming</strong></p><p>Functional Programming 大部分的人应该多少都有接触过，这也是 Rx 学习过程中的重点之一，我们之后会花两天的篇幅来细讲 Functional Programming。
如果要用一句话来总结 Functional Programming，那就是 <strong>用 function 来思考我们的问题，以及撰写程式</strong></p><blockquote><p>在下一篇文章会更深入的讲解 Functional Programming</p></blockquote><p><strong>Reactive Programming</strong></p><blockquote><p>很多人一谈到 Reactive Programming 就会直接联想到是在讲 RxJS，但实际上 Reactive Programming 仍是一种编程范式，在不同的场景都有机会遇到，而非只存在于 RxJS，尤雨溪(Vue 的作者)就曾在 twitter 对此表达不满！</p></blockquote><p><img src="https://res.cloudinary.com/dohtkyi84/image/upload/v1480531809/%E8%9E%A2%E5%B9%95%E5%BF%AB%E7%85%A7_2016-11-30_%E4%B8%8A%E5%8D%886.23.49_zdniva.png" alt="Evan You 的推文"></p><p>Reactive Programming 简单来说就是 <strong>当变数或资源发生变动时，由变数或资源自动告诉我发生变动了</strong></p><p>这句话看似简单，其实背后隐含两件事</p><ul><li>当发生变动 =&gt; 非同步：不知道什么时候会发生变动，反正变动时要跟我说</li><li>由变数自动告知我 =&gt; 我不用写通知我的每一步代码</li></ul><p>由于最近很红的 Vue.js 底层就是用 Reactive Programming 的概念实例，让我能很好的举例，让大家理解什么是 Reactive Programming！</p><p>当我们在使用 vue 开发时，只要一有绑定的变数发生改变，相关的变数及画面也会跟着变动，而开发者不需要写这其中如何<strong>通知</strong>发生变化的每一步代码，只需要<strong>专注在发生变化时要做什么事</strong>，这就是典型的 Reactive Programming (记得必须是由变数或资源主动告知！)</p><blockquote><p>Vue.js 在做 two-ways data binding 是透过 ES5 definedProperty 的 getter/setter。每当变数发生变动时，就会执行 getter/setter 从而收集有改动的变数，这也被称为<strong>依赖收集</strong>。</p></blockquote><p>Rx 基本上就是上述的两个观念的结合，这个部份读者在看完之后的文章，会有更深的体悟。</p><h2 id="今日小结"><a href="#今日小结" aria-hidden="true" class="header-anchor">#</a> 今日小结</h2><p>今天这篇文章主要是带大家了解为什么我们需要 RxJS，以及 RxJS 的基本介绍。若读者还不太能吸收本文的内容，可以过一段时间后再回来看这篇文章会有更深的体会，或是在下方留言给我！</p></div></div></div><div class="v-card__actions"><div class="flex xs12"><a href="/BLOG/tags/RXJS"><span tabindex="0" class="v-chip capitalize chip-tag v-chip--label v-chip--small"><span class="v-chip__content">RXJS</span></span></a></div></div></article></div><div class="flex text-xs-left xs6"><a href="/BLOG/posts/rxjs02.html" class="post-nav v-btn v-btn--flat v-btn--router"><div class="v-btn__content"><div class="grey--text"><i class="fa mr-1 fa-chevron-left"></i>Prev</div><div class="title mt-1 primary--text hidden-xs-only">02Functional Programming 基本观念</div></div></a></div><div class="flex text-xs-right xs6"><a href="/BLOG/posts/rxjs00.html" class="post-nav v-btn v-btn--flat v-btn--router"><div class="v-btn__content"><div class="grey--text">Next
          <i class="fa ml-1 fa-chevron-right"></i></div><div class="title mt-1 primary--text hidden-xs-only">00关于本系列文章</div></div></a></div><div class="flex mt-3 xs12"><div class="v-card" style="height:undefined;"><div class="v-card__title"><span class="headline">Comment</span></div></div></div></div></div><footer class="v-footer blog-footer darken-1 mt-3 theme--dark" style="height:auto;"><div class="primary--text text--lighten-4 text-xs-center py-3 v-card v-card--flat v-card--tile primary" style="height:undefined;"><div class="v-card__text pb-0">博客内容遵循 <a rel="license noopener noreferrer" href="https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh" target="_blank">知识共享 署名 - 非商业性 - 相同方式共享 4.0 国际协议</a></div><div class="v-card__text pt-0 mt-1"><span>訾绍飞 © 2015 - 2018</span><span><!---->
        Power by
        <a href="https://vuepress.vuejs.org" target="_blank" rel="noopener noreferrer">VuePress</a> Theme
        <a href="https://github.com/ShaofeiZi/BLOG" target="_blank" rel="noopener noreferrer">indigo</a></span></div></div></footer></div></main><button type="button" class="v-btn v-btn--bottom v-btn--floating v-btn--fixed v-btn--right accent" style="display:none;"><div class="v-btn__content"><i class="fa fa-lg fa-chevron-up"></i></div></button></div></div></div>
    <script src="/BLOG/assets/js/33.ad2b89cc.js" defer></script><script src="/BLOG/assets/js/app.1a725be8.js" defer></script>
  </body>
</html>
